﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Text;
using PickGold.Callers;

namespace PickGold
{
	/// <summary>
	/// 异步操作的状态操作
	/// </summary>
	public interface IAsyncResultWrap : IAsyncResult
	{
		/// <summary>
		/// 无效次数
		/// </summary>
		int Invalids { set; get; }
		/// <summary>
		/// 回调次数
		/// </summary>
		int Callbacks { set; get; }
		/// <summary>
		/// 最后时间
		/// </summary>
		DateTime WrapLast { set; get; }
		/// <summary>
		/// 获取用户定义的对象，它限定或包含关于异步操作的信息
		/// </summary>
		object WrapTag { set; get; }
		/// <summary>
		/// 异步调用结果
		/// </summary>
		object WrapReturn { set; get; }
		/// <summary>
		/// 异步调用结果输出参数列表，按调用函数列表顺序
		/// </summary>
		object[] WrapOutput { set; get; }
		/// <summary>
		/// 获取异步操作错误
		/// </summary>
		Exception WrapError { set; get; }
		/// <summary>
		/// 获取或设置原异步操作的状态；仅可设置一次
		/// </summary>
		IAsyncResult WrapResult { set; get; }
		/// <summary>
		/// 获取原引用在相应异步操作完成时调用的方法
		/// </summary>
		AsyncCallback WrapCallback { set; get; }
		/// <summary>
		/// 结束调用函数引用
		/// </summary>
		Delegate WrapEnd { set; get; }

		/// <summary>
		/// 通知已完成，删除 WrapResult 异步调用状态，通知 AsyncWaitHandle 等待线程继续，调用 WrapCallback 异步回调函数。
		/// </summary>
		/// <returns>闭包返回</returns>
		IAsyncResultWrap Complete();

		/// <summary>
		/// 阻止当前线程，直到当前 System.Threading.WaitHandle 收到信号。
		/// </summary>
		/// <returns>如果当前实例收到信号，则为 true。如果当前实例永远收不到信号，则永不返回。</returns>
		bool WaitOne();
	}

	/// <summary>
	/// 异步包装
	/// </summary>
	public class AsyncResultWrap : IAsyncResultWrap, IAsyncResult, IDisposable
	{
		#region inner class

		class InnerSyncWaitHandle : WaitHandle
		{
			public override bool WaitOne()
			{
				return true;//return base.WaitOne();
			}

			public override bool WaitOne(int millisecondsTimeout)
			{
				return true;//return base.WaitOne(millisecondsTimeout);
			}

			public override bool WaitOne(int millisecondsTimeout, bool exitContext)
			{
				return true;//return base.WaitOne(millisecondsTimeout, exitContext);
			}

			public override bool WaitOne(TimeSpan timeout)
			{
				return true;//return base.WaitOne(timeout);
			}

			public override bool WaitOne(TimeSpan timeout, bool exitContext)
			{
				return true;//return base.WaitOne(timeout, exitContext);
			}
		}

		#endregion

		/// <summary>
		/// 同步完成线程等待对象，该对象所有等待方法都将立刻返回
		/// </summary>
		public readonly static WaitHandle SyncWaitHandle = new InnerSyncWaitHandle();

		/// <summary>
		/// 用户定义的对象，它限定或包含关于异步操作的信息。
		/// </summary>
		public object AsyncState;

		/// <summary>
		/// 该值指示异步操作是否同步完成。
		/// </summary>
		public bool CompletedSynchronously;

		/// <summary>
		/// 该值指示异步操作是否已完成。
		/// </summary>
		public bool IsCompleted;

		/// <summary>
		/// 无效次数
		/// </summary>
		public int Invalids;
		/// <summary>
		/// 回调次数
		/// </summary>
		public int Callbacks;
		/// <summary>
		/// 最后时间
		/// </summary>
		public DateTime WrapLast;
		/// <summary>
		/// 获取用户定义的对象，它限定或包含关于异步操作的信息
		/// </summary>
		public object WrapTag;
		/// <summary>
		/// 异步调用结果
		/// </summary>
		public object WrapReturn;
		/// <summary>
		/// 异步调用结果输出参数列表，按调用函数列表顺序
		/// </summary>
		public object[] WrapOutput;
		/// <summary>
		/// 获取异步操作错误
		/// </summary>
		public Exception WrapError;
		/// <summary>
		/// 获取或设置原异步操作的状态；如果为空表示异步处理已完成，代替 IAsyncResult.IsCompleted 成员。
		/// </summary>
		public IAsyncResult WrapResult;
		/// <summary>
		/// 获取原引用在相应异步操作完成时调用的方法
		/// </summary>
		public AsyncCallback WrapCallback;
		/// <summary>
		/// 结束调用函数引用
		/// </summary>
		public Delegate WrapEnd;

		/// <summary>
		/// 最多异步次数，同步完成应等于零，一次完成，则 IAsyncResult 各属性返回 WrapResult 成员内容
		/// </summary>
		private readonly int _MaxStep;

		private WaitHandle _WaitHandle;//ManualResetEvent//DoubleWaitHandle//WaitHandle//EventWaitHandle

		/// <summary>
		/// 使用一个异步操作状态构造一个异步操作包装器实例
		/// </summary>
		/// <param name="maxStep">默认为一次异步</param>
		public AsyncResultWrap(int maxStep) : this(maxStep, null, null, null) { }

		/// <summary>
		/// 使用一个异步操作状态构造一个异步操作包装器实例
		/// </summary>
		/// <param name="maxStep">默认为一次异步</param>
		/// <param name="asyncResult">需要包装的异步操作状态</param>
		public AsyncResultWrap(int maxStep, IAsyncResult asyncResult) : this(maxStep, asyncResult, null, null) { }

		/// <summary>
		/// 使用一个异步操作状态构造一个异步操作包装器实例
		/// </summary>
		/// <param name="maxStep">默认为一次异步</param>
		/// <param name="asyncCallback">异步操作回调委托</param>
		/// <param name="asyncState">附加的异步操作状态的用户定义对象</param>
		public AsyncResultWrap(int maxStep, AsyncCallback asyncCallback, object asyncState) : this(maxStep, null, asyncCallback, asyncState) { }

		/// <summary>
		/// 使用一个异步操作状态构造一个异步操作包装器实例
		/// </summary>
		/// <param name="maxStep">默认为一次异步</param>
		/// <param name="asyncResult">需要包装的异步操作状态</param>
		/// <param name="asyncCallback">异步操作回调委托</param>
		/// <param name="asyncState">附加的异步操作状态的用户定义对象</param>
		public AsyncResultWrap(int maxStep, IAsyncResult asyncResult, AsyncCallback asyncCallback, object asyncState)
		{
			this._MaxStep = maxStep;
			this.WrapCallback = asyncCallback;
			this.AsyncState = asyncState;
		}

		/// <summary>
		/// 通知已完成，通知 AsyncWaitHandle 等待线程继续，调用 WrapCallback 异步回调函数。
		/// </summary>
		/// <param name="error"></param>
		public IAsyncResultWrap Complete(Exception error)
		{
			this.WrapError = error;
			return this.Complete();
		}

		/// <summary>
		/// 通知已完成，通知 AsyncWaitHandle 等待线程继续，调用 WrapCallback 异步回调函数。
		/// </summary>
		/// <param name="value"></param>
		/// <param name="output"></param>
		public IAsyncResultWrap Complete(object value, params object[] output)
		{
			this.WrapReturn = value;
			this.WrapOutput = output;
			return this.Complete();
		}

		/// <summary>
		/// 未走异步的同步完成操作
		/// </summary>
		/// <param name="asyncError">异步异常，未发生异步应为空</param>
		/// <returns>异步状态</returns>
		public IAsyncResultWrap SyncComplete(Exception asyncError)
		{
			this.WrapError = asyncError;
			this.CompletedSynchronously = true;
			this._WaitHandle = SyncWaitHandle;
			return this.Complete();
		}

		/// <summary>
		/// 未走异步的同步完成操作
		/// </summary>
		/// <param name="asyncReturn">异步返回值</param>
		/// <param name="asyncOutput">异步传出参数</param>
		/// <returns>异步状态</returns>
		public IAsyncResultWrap SyncComplete(object asyncReturn, object[] asyncOutput)
		{
			this.WrapReturn = asyncReturn;
			this.WrapOutput = asyncOutput;
			this.CompletedSynchronously = true;
			this._WaitHandle = SyncWaitHandle;
			return this.Complete();
		}

		/// <summary>
		/// 最多异步次数，同步完成应等于零，一次完成，则 IAsyncResult 各属性返回 WrapResult 成员内容
		/// </summary>
		public int MaxStep
		{
			get
			{
				return this._MaxStep;
			}
		}

		/// <summary>
		/// 获取 WrapWaitHandle 属性值，如果为空则构造对象并返回
		/// </summary>
		public WaitHandle AsyncWaitHandle
		{
			get
			{
				if (this._MaxStep == 1 && this.WrapResult != null)
					return this.WrapResult.AsyncWaitHandle;

				if (this.IsCompleted && this.WrapResult != null)
					return this.WrapResult.AsyncWaitHandle;

				if (!Monitor.TryEnter(this, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this);
				try
				{
					if (this._WaitHandle == null)
					{
						if (this.IsCompleted)
							this._WaitHandle = SyncWaitHandle;//new ManualResetEvent(DoubleWaitHandle.CONTINUE);
						else
							this._WaitHandle = new ManualResetEvent(DoubleWaitHandle.PAUSE);// new DoubleWaitHandle(this._AsyncResult == null ? null : this._AsyncResult.AsyncWaitHandle, false);
					}
				}
				finally
				{
					Monitor.Exit(this);
				}
				return this._WaitHandle;
			}
		}

		/// <summary>
		/// 包装线程同步对象，不般不等于 IAsyncResult.AsyncWaitHandle 属性值
		/// </summary>
		public WaitHandle WrapWaitHandle
		{
			set
			{
				if (!Monitor.TryEnter(this, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this);
				try
				{
					if (this._WaitHandle == null)
						this._WaitHandle = value;
				}
				finally
				{
					Monitor.Exit(this);
				}
			}
			get
			{
				return this._WaitHandle;
			}
		}

		#region IAsyncResult

		object IAsyncResult.AsyncState
		{
			get
			{
				return this.AsyncState;
			}
		}
		WaitHandle IAsyncResult.AsyncWaitHandle
		{
			get
			{
				return this.AsyncWaitHandle;
			}
		}
		bool IAsyncResult.CompletedSynchronously
		{
			get
			{
				if (this._MaxStep == 0)
					return true;

				if (this.IsCompleted && this.WrapResult == null)
					return true;

				if (this._MaxStep == 1 && this.WrapResult != null)
					return this.WrapResult.CompletedSynchronously;

				return this.CompletedSynchronously;
			}
		}
		bool IAsyncResult.IsCompleted
		{
			get
			{
				if (this._MaxStep == 1 && this.WrapResult != null)
					return this.WrapResult.IsCompleted;

				return this.IsCompleted;
			}
		}

		#endregion

		#region IAsyncResultWrap

		int IAsyncResultWrap.Invalids
		{
			set
			{
				this.Invalids = value;
			}
			get
			{
				return this.Invalids;
			}
		}
		int IAsyncResultWrap.Callbacks
		{
			set
			{
				this.Callbacks = value;
			}
			get
			{
				return this.Callbacks;
			}
		}
		DateTime IAsyncResultWrap.WrapLast
		{
			set
			{
				this.WrapLast = value;
			}
			get
			{
				return this.WrapLast;
			}
		}
		object IAsyncResultWrap.WrapTag
		{
			set
			{
				this.WrapTag = value;
			}
			get
			{
				return this.WrapTag;
			}
		}
		object IAsyncResultWrap.WrapReturn
		{
			set
			{
				this.WrapReturn = value;
			}
			get
			{
				return this.WrapReturn;
			}
		}
		object[] IAsyncResultWrap.WrapOutput
		{
			set
			{
				this.WrapOutput = value;
			}
			get
			{
				return this.WrapOutput;
			}
		}
		Exception IAsyncResultWrap.WrapError
		{
			set
			{
				this.WrapError = value;
			}
			get
			{
				return this.WrapError;
			}
		}
		IAsyncResult IAsyncResultWrap.WrapResult
		{
			set
			{
				this.WrapResult = value;
			}
			get
			{
				return this.WrapResult;
			}
		}
		AsyncCallback IAsyncResultWrap.WrapCallback
		{
			set
			{
				this.WrapCallback = value;
			}
			get
			{
				return this.WrapCallback;
			}
		}
		Delegate IAsyncResultWrap.WrapEnd
		{
			set
			{
				this.WrapEnd = value;
			}
			get
			{
				return this.WrapEnd;
			}
		}

		/// <summary>
		/// 通知已完成，通知 AsyncWaitHandle 等待线程继续，调用 WrapCallback 异步回调函数。
		/// </summary>
		/// <returns>闭包返回</returns>
		public IAsyncResultWrap Complete()
		{
			this.IsCompleted = true;
			if (!this.CompletedSynchronously && this.WrapResult == null)
				this.CompletedSynchronously = true;
			if (!Monitor.TryEnter(this, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this);
			try
			{
				var w = this._WaitHandle as EventWaitHandle;
				if (w != null)
					w.Set();
			}
			finally
			{
				Monitor.Exit(this);
			}
			if (this.WrapCallback != null)
				this.WrapCallback(this);
			return this;
		}

		/// <summary>
		/// 阻止当前线程，直到当前 System.Threading.WaitHandle 收到信号。
		/// </summary>
		/// <returns>如果当前实例收到信号，则为 true。如果当前实例永远收不到信号，则永不返回。</returns>
		public bool WaitOne()
		{
			if (!Monitor.TryEnter(this, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this);
			try
			{
				if (this.IsCompleted)
					return true;

				if (this._MaxStep == 1 && this.WrapResult != null)
					return this.WrapResult.AsyncWaitHandle.WaitOne();

				if (this._WaitHandle == null)
					this._WaitHandle = new ManualResetEvent(this.IsCompleted ? DoubleWaitHandle.CONTINUE : DoubleWaitHandle.PAUSE);// new DoubleWaitHandle(this._AsyncResult == null ? null : this._AsyncResult.AsyncWaitHandle, false);
			}
			finally
			{
				Monitor.Exit(this);
			}
			return this._WaitHandle.WaitOne();
		}

		#endregion

		/// <summary>
		/// 执行与释放或重置非托管资源相关的应用程序定义的任务。
		/// </summary>
		public void Dispose()
		{
			if (!Monitor.TryEnter(this, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this);
			try
			{
				if (this._WaitHandle != null)
					this._WaitHandle.Dispose();
			}
			finally
			{
				Monitor.Exit(this);
			}
		}

		/// <summary>
		/// 调用回调函数
		/// </summary>
		/// <param name="result">异步操作状态</param>
		public static void Callback(IAsyncResult result)
		{
			var ar = result.AsyncState as IAsyncResultWrap;
			if (ar == null)
				throw new InvalidCastException("When begin invoke async calling, The last callback parameter(state) must be IAsyncResultWrap instance.");

			ar.Complete();
		}

		/// <summary>
		/// 未走异步的同步完成操作
		/// </summary>
		/// <param name="asyncError">异步异常，未发生异步应为空</param>
		/// <param name="asyncCallback">传入的异步回调</param>
		/// <param name="asyncState">传入的异步状态或限制</param>
		/// <returns>异步状态</returns>
		public static IAsyncResultWrap SyncComplete(Exception asyncError, AsyncCallback asyncCallback, object asyncState)
		{
			var ar = new AsyncResultWrap(0, asyncCallback, asyncState);
			ar.WrapError = asyncError;
			ar.CompletedSynchronously = true;
			ar._WaitHandle = SyncWaitHandle;
			ar.Complete();
			return ar;
		}

		/// <summary>
		/// 未走异步的同步完成操作
		/// </summary>
		/// <param name="asyncReturn">异步返回值</param>
		/// <param name="asyncOutput">异步传出参数</param>
		/// <param name="asyncCallback">传入的异步回调</param>
		/// <param name="asyncState">传入的异步状态或限制</param>
		/// <returns>异步状态</returns>
		public static IAsyncResultWrap SyncComplete(object asyncReturn, object[] asyncOutput, AsyncCallback asyncCallback, object asyncState)
		{
			var ar = new AsyncResultWrap(0, asyncCallback, asyncState);
			ar.WrapReturn = asyncReturn;
			ar.WrapOutput = asyncOutput;
			ar.CompletedSynchronously = true;
			ar._WaitHandle = SyncWaitHandle;
			ar.Complete();
			return ar;
		}
	}
}
